package redis;

import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.jedis.JedisClientConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import redis.clients.jedis.JedisPoolConfig;

import java.time.Duration;

import static org.apache.logging.log4j.util.Strings.isNotBlank;

/**
 * @author songZiHao
 * @version 1.0.0
 * @ClassName MyRedisConfiguration.java
 * @Description TODO
 * @createTime 2021年04月20日 15:12:00
 */
@EnableConfigurationProperties(RedisProperties.class)
public class MyRedisConfiguration {
    private RedisProperties redisProperties;

    public MyRedisConfiguration(RedisProperties redisProperties) {
        this.redisProperties = redisProperties;
    }

    private JedisPoolConfig jedisPoolConfig() {
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        // 最大连接数
        jedisPoolConfig.setMaxTotal(redisProperties.getJedis().getPool().getMaxActive());
        // 当池内没有可用连接时，最大等待时间
        jedisPoolConfig.setMaxWaitMillis(redisProperties.getJedis().getPool().getMaxWait().toMillis());
        // 最大空闲连接数
        jedisPoolConfig.setMinIdle(redisProperties.getJedis().getPool().getMaxIdle());
        // 最小空闲连接数
        jedisPoolConfig.setMinIdle(redisProperties.getJedis().getPool().getMinIdle());
        // 是否在空闲资源监测时通过ping命令监测连接有效性，无效连接将被销毁。
        jedisPoolConfig.setTestWhileIdle(true);
        // 空闲资源的检测周期（单位为毫秒），默认1分钟
        Duration timeBetweenEvictionRuns = redisProperties.getJedis().getPool().getTimeBetweenEvictionRuns();
        jedisPoolConfig.setTimeBetweenEvictionRunsMillis(
            timeBetweenEvictionRuns == null ? 60000 : timeBetweenEvictionRuns.toMillis());
        // 资源池中资源的最小空闲时间（单位为毫秒），默认2分钟，达到此值后空闲资源将被移除。
        jedisPoolConfig.setMinEvictableIdleTimeMillis(120000);
        // 做空闲资源检测时，每次检测资源的个数，如果设置为 -1，就是对所有连接做空闲监测
        jedisPoolConfig.setNumTestsPerEvictionRun(-1);
        return jedisPoolConfig;
    }

    @Bean
    public JedisConnectionFactory jedisConnectionFactory() {
        return doCreateJedisConnectionFactory(redisProperties.getDatabase());
    }

    private JedisConnectionFactory doCreateJedisConnectionFactory(int database) {
        JedisClientConfiguration jedisClientConfiguration = JedisClientConfiguration.builder().usePooling()
            .poolConfig(jedisPoolConfig()).and().readTimeout(redisProperties.getTimeout()).build();
        RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
        redisStandaloneConfiguration.setHostName(redisProperties.getHost());
        redisStandaloneConfiguration.setPort(redisProperties.getPort());
        if (isNotBlank(redisProperties.getPassword())) {
            redisStandaloneConfiguration.setPassword(RedisPassword.of(redisProperties.getPassword()));
        }
        redisStandaloneConfiguration.setDatabase(database);
        return new JedisConnectionFactory(redisStandaloneConfiguration, jedisClientConfiguration);
    }

    @Bean
    public MyRedisClient redisFacade(RedisTemplate redisTemplate) {
        return new MyRedisClient(redisTemplate);
    }
}
